#include "ScreenMenu.h"

char Interpolation(int a, int b, float coefficient)
{
	return (char)(a + coefficient * (b - a));
}
// Tous le setting des menus (visuel, position, etc.) 
ScreenMenu::ScreenMenu()
	: SDLSprite()
	, screenWidth(0)
	, screenHeight(0)
	, numberMatrixCaseX(0)
	, numberMatrixCaseY(0)
	, caseWidth(0)
	, caseHeight(0)
{
	dstRect.x = 0;
	dstRect.y = 0;

	coinHautGauche = SDLResources::GetInstance()->GetTexture("Assets\\Artworks\\Menu\\HautGauche.png");
	coinHautDroit  = SDLResources::GetInstance()->GetTexture("Assets\\Artworks\\Menu\\HautDroit.png");
	coinBasGauche  = SDLResources::GetInstance()->GetTexture("Assets\\Artworks\\Menu\\BasDroit.png");
	coinBasDroit   = SDLResources::GetInstance()->GetTexture("Assets\\Artworks\\Menu\\BasGauche.png");

	bordHaut   = SDLResources::GetInstance()->GetTexture("Assets\\Artworks\\Menu\\bordHaut.bmp");
	bordDroit  = SDLResources::GetInstance()->GetTexture("Assets\\Artworks\\Menu\\bordDroit.bmp");
	bordGauche = SDLResources::GetInstance()->GetTexture("Assets\\Artworks\\Menu\\BordGauche.bmp");
	bordBas    = SDLResources::GetInstance()->GetTexture("Assets\\Artworks\\Menu\\bordBas.bmp");
}


ScreenMenu::ScreenMenu(int positionX, int positionY, int screenWidth, int screenHeight, int numberMatrixCaseX, int numberMatrixCaseY, SDL_Color* TextColor, int fontSizeMenu, std::string fileFont)
	: SDLSprite()
	, screenWidth(screenWidth)
	, screenHeight(screenHeight)
	, numberMatrixCaseX(numberMatrixCaseX)
	, numberMatrixCaseY(numberMatrixCaseY)
	, numberMenu(numberMatrixCaseX * numberMatrixCaseY)
	, caseWidth(0)
	, caseHeight(0)
	, fontSize(fontSizeMenu)
	, fileFont(fileFont)
	, menucanselected(false)
	, selectTexteEnCour(0)
	, curseur(nullptr)
	, returnSelection(-1)
	, isActivated(false)
{
	glowColor.r = 255;
	glowColor.g = 255;
	glowColor.b = 0;

	if(screenWidth % 2 == 1)
	{
		screenWidth++;
		this->screenWidth++;
	}

	if(screenHeight % 2 == 1)
	{
		screenHeight++;
		this->screenHeight++;
	}

	dstRect.x = positionX;
	dstRect.y = positionY;

	oldPositionX = dstRect.x;
	oldPositionY = dstRect.y;

	if(TextColor == nullptr)
	{
		couleur.r = 255;
		couleur.g = 255;
		couleur.b = 255;
	}
	else
	{
		couleur.r = TextColor->r;
		couleur.g = TextColor->g;
		couleur.b = TextColor->b;
	}

	mesure.x = dstRect.x + 25;
	mesure.y = dstRect.y + 15;
	mesure.w = 0;
	mesure.h = 0;

	coinHautGauche = SDLResources::GetInstance()->GetTexture("Assets\\Artworks\\Menu\\HautGauche.png");
	coinHautDroit  = SDLResources::GetInstance()->GetTexture("Assets\\Artworks\\Menu\\HautDroit.png");
	coinBasGauche  = SDLResources::GetInstance()->GetTexture("Assets\\Artworks\\Menu\\BasDroit.png");
	coinBasDroit   = SDLResources::GetInstance()->GetTexture("Assets\\Artworks\\Menu\\BasGauche.png");

	bordHaut   = SDLResources::GetInstance()->GetTexture("Assets\\Artworks\\Menu\\bordHaut.bmp");
	bordDroit  = SDLResources::GetInstance()->GetTexture("Assets\\Artworks\\Menu\\bordDroit.bmp");
	bordGauche = SDLResources::GetInstance()->GetTexture("Assets\\Artworks\\Menu\\BordGauche.bmp");
	bordBas    = SDLResources::GetInstance()->GetTexture("Assets\\Artworks\\Menu\\bordBas.bmp");

	curseur = new SDLSprite("Assets\\Artworks\\cursor.png");

	backGroundTexture = SDL_CreateTexture(SDLRenderer::GetInstance()->GetRenderer(), SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_STREAMING, screenWidth + 15, screenHeight + 15);
	BlitToBackGroundTexture(screenWidth + 15, screenHeight + 15);

	
}


ScreenMenu::~ScreenMenu()
{
	SDL_DestroyTexture(backGroundTexture);

	std::vector<SDLTexte*>::iterator iter;

	for(iter = listeTexte.begin(); iter != listeTexte.end(); iter++)
	{
		delete (*iter);
	}

		delete curseur;
}


int ScreenMenu::GetMenuSelection()
{
	if(returnSelection != -1)
	{
		int temps = returnSelection;
		returnSelection = -1;
		return temps;
	}

	return returnSelection;		// return -1
}

void ScreenMenu::AddMenuPosition()
{
	int width = 0;
	int height = 0;
	int count = 0;
	int positionEnCour;
	int multiply;

	positionEnCour = listeTexte.size();

	if(positionEnCour != 1  &&  (positionEnCour -1) / numberMatrixCaseY  != (positionEnCour -2) / numberMatrixCaseY)
	{
		mesure.x = listeTexte[positionEnCour - numberMatrixCaseY - 1]->GetX() + mesure.w + 35;
		mesure.y = listeTexte[positionEnCour - numberMatrixCaseY - 1]->GetY();
		mesure.w = 0;
		mesure.h = 0;
	}

	SDLTexte* addTexte = listeTexte[positionEnCour - 1];

	SDL_QueryTexture(addTexte->GetTexture(), 0, 0, &width, &height);

	if(width > mesure.w)
	{
		mesure.w = width;
	}
	if(height > mesure.h)
	{
		mesure.h = height;
	}

	multiply = ((positionEnCour - 1) % numberMatrixCaseY);

	addTexte->SetPosition(mesure.x, mesure.y + mesure.h * multiply + 10 * multiply);

	// pour la selection
	if(menucanselected == false  &&  addTexte->GetCanSelectTexte() == true)
	{
		curseur->SetPosition(addTexte->GetX() - 35, addTexte->GetY());
		selectTexteEnCour = positionEnCour - 1;

		menucanselected = true;
	}
}

void ScreenMenu::AddMenu(std::string menuText, bool canSelectTexte, bool canGlow)
{
	if(listeTexte.size() < numberMenu)
	{

		SDLTexte* addTexte = new SDLTexte(menuText.c_str(), fileFont.c_str(), 0, 0, &couleur, fontSize);
		SDLTexte* addTexteGlow = nullptr;

		listeTexte.push_back(addTexte);

		addTexte->SetCanSelectTexte(canSelectTexte);

		AddMenuPosition();

		if(canGlow)
		{
			addTexteGlow = new SDLTexte(menuText.c_str(), fileFont.c_str(), addTexte->GetX(),  addTexte->GetY(), &glowColor, fontSize);
			addTexteGlow->SetVisible(false);
		}
		listeGlowTexte.push_back(addTexteGlow);
	}
}

SDLTexte* ScreenMenu::AddVariableMessageMenu(std::string* menuText, bool canSelectTexte, bool canGlow)
{
	if(listeTexte.size() < numberMenu)
	{
		SDLTexte* addTexte = new SDLTexte(menuText, fileFont.c_str(), 0, 0, &couleur, fontSize);
		SDLTexte* addTexteGlow = nullptr;

		listeTexte.push_back(addTexte);

		addTexte->SetCanSelectTexte(canSelectTexte);

		AddMenuPosition();

		if(canGlow)
		{
			addTexteGlow = new SDLTexte(menuText, fileFont.c_str(), addTexte->GetX(),  addTexte->GetY(), &glowColor, fontSize);
			addTexteGlow->SetVisible(false);
		}
		listeGlowTexte.push_back(addTexteGlow);

		return addTexte;
	}

	return nullptr;
}


SDLTexte* ScreenMenu::AddVariableMenu(int* linkVariable, bool canSelectTexte, bool canGlow)
{
	if(listeTexte.size() < numberMenu)
	{
		SDLTexte* addTexte = new SDLTexte(linkVariable, fileFont.c_str(), 0, 0, &couleur, fontSize);
		SDLTexte* addTexteGlow = nullptr;

		listeTexte.push_back(addTexte);

		addTexte->SetCanSelectTexte(canSelectTexte);

		AddMenuPosition();

		if(canGlow)
		{
			addTexteGlow = new SDLTexte(linkVariable, fileFont.c_str(), addTexte->GetX(),  addTexte->GetY(), &glowColor, fontSize);
			addTexteGlow->SetVisible(false);
		}
		listeGlowTexte.push_back(addTexteGlow);

		return addTexte;
	}

	return nullptr;
}


SDLTexte* ScreenMenu::AddVariableAndTexteMenu(std::string beginText, int* linkVariable, std::string endText, bool canSelectTexte, bool canGlow)
{
	if(listeTexte.size() < numberMenu)
	{
		SDLTexte* addTexte = new SDLTexte(beginText, linkVariable, endText, fileFont.c_str(), 0, 0, &couleur, fontSize);
		SDLTexte* addTexteGlow = nullptr;

		listeTexte.push_back(addTexte);
		addTexte->SetCanSelectTexte(canSelectTexte);

		AddMenuPosition();

		if(canGlow)
		{
			addTexteGlow = new SDLTexte(beginText, linkVariable, endText, fileFont.c_str(), addTexte->GetX(),  addTexte->GetY(), &glowColor, fontSize);
			addTexteGlow->SetVisible(false);
		}
		listeGlowTexte.push_back(addTexteGlow);

		return addTexte;
	}

	return nullptr;
}

void ScreenMenu::ShowGlowTexteMenu(int indexMenu, bool isGlow)
{
	if(listeGlowTexte.size() > indexMenu  &&  listeGlowTexte[indexMenu] != nullptr)
	{
		if(isGlow == true)
		{
			listeTexte[indexMenu]->SetVisible(false);
			listeGlowTexte[indexMenu]->SetVisible(true);
		}
		else
		{
			listeTexte[indexMenu]->SetVisible(true);
			listeGlowTexte[indexMenu]->SetVisible(false);
		}
	}
}

void ScreenMenu::UpdateMenuWindows()
{
	int maxX = listeTexte[0]->GetX();
	int maxY =  listeTexte[0]->GetY();
	int width = 0;
	int height = 0;
	SDL_DestroyTexture(backGroundTexture);
	backGroundTexture = nullptr;

	std::vector<SDLTexte*>::iterator iter;
	for(iter = listeTexte.begin(); iter != listeTexte.end(); iter++)
	{
		if(maxX < (*iter)->GetX())
		{
			maxX = (*iter)->GetX();
		}
		if(maxY < (*iter)->GetY())
		{
			maxY = (*iter)->GetY();
		}
	}

	SDL_QueryTexture(listeTexte[listeTexte.size() - 1]->GetTexture(), 0, 0, &width, &height);
	screenWidth = maxX - dstRect.x + width;
	screenHeight = maxY - dstRect.x + height;

	backGroundTexture = SDL_CreateTexture(SDLRenderer::GetInstance()->GetRenderer(), SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_STREAMING, screenWidth + 15, screenHeight + 15);
	BlitToBackGroundTexture(screenWidth + 15, screenHeight + 15);

	if(screenWidth % 2 == 1)
	{
		screenWidth++;
	}

	if(screenHeight % 2 == 1)
	{
		screenHeight++;
	}
}


void ScreenMenu::Draw()
{
	if(visible)
	{
		if(oldPositionX != dstRect.x  ||  oldPositionY != dstRect.y)
		{
			for(std::vector<SDLTexte*>::iterator iter = listeTexte.begin(); iter != listeTexte.end(); iter++)
			{
				(*iter)->SetPosition((*iter)->GetX() + (dstRect.x - oldPositionX), (*iter)->GetY() + (dstRect.y - oldPositionY));
			}

			for(std::vector<SDLTexte*>::iterator iter = listeGlowTexte.begin(); iter != listeGlowTexte.end(); iter++)
			{
				if((*iter) != nullptr)
				{
					(*iter)->SetPosition((*iter)->GetX() + (dstRect.x - oldPositionX), (*iter)->GetY() + (dstRect.y - oldPositionY));
				}
			}

			curseur->SetPosition(curseur->GetX() + (dstRect.x - oldPositionX), curseur->GetY() + (dstRect.y - oldPositionY));

			oldPositionX = dstRect.x;
			oldPositionY = dstRect.y;
		}

		ApplySurfaceMenu(dstRect.x + 5, dstRect.y + 5, backGroundTexture, SDLRenderer::GetInstance()->GetRenderer());

		ApplySurfaceMenu(dstRect.x, dstRect.y, coinHautGauche, SDLRenderer::GetInstance()->GetRenderer());
		ApplySurfaceMenu(dstRect.x + screenWidth + COIN_SIZE, dstRect.y, coinHautDroit, SDLRenderer::GetInstance()->GetRenderer());

		ApplySurfaceMenu(dstRect.x + screenWidth + COIN_SIZE, dstRect.y + screenHeight + COIN_SIZE, coinBasGauche, SDLRenderer::GetInstance()->GetRenderer());
		ApplySurfaceMenu(dstRect.x, dstRect.y + screenHeight + COIN_SIZE, coinBasDroit, SDLRenderer::GetInstance()->GetRenderer());

		int screenWidthDiv = screenWidth / 2;
		int screenHeightDiv = screenHeight / 2;

		for(int i = 0; i < screenHeightDiv; i++)
		{
			ApplySurfaceMenu(dstRect.x + screenWidth + COIN_SIZE + COIN_SIZE/2, dstRect.y + COIN_SIZE + i*2, bordDroit, SDLRenderer::GetInstance()->GetRenderer());
			ApplySurfaceMenu(dstRect.x,                                         dstRect.y + COIN_SIZE + i*2, bordGauche, SDLRenderer::GetInstance()->GetRenderer());
		}

		for(int i = 0; i < screenWidthDiv; i++)
		{
			ApplySurfaceMenu(dstRect.x + COIN_SIZE + i*2, dstRect.y,                                          bordHaut, SDLRenderer::GetInstance()->GetRenderer());
			ApplySurfaceMenu(dstRect.x + COIN_SIZE + i*2, dstRect.y + screenHeight + COIN_SIZE + COIN_SIZE/2, bordBas, SDLRenderer::GetInstance()->GetRenderer());
		}

		curseur->SetVisible(menucanselected);

	}
}

void ScreenMenu::ApplySurfaceMenu(int x, int y, SDL_Texture* texture, SDL_Renderer* renderer)
{
	rect.x = x;
	rect.y = y;
	SDL_QueryTexture(texture, 0, 0, &rect.w, &rect.h);
	SDL_RenderCopy(renderer, texture, 0, &rect);
}


void ScreenMenu::BlitToBackGroundTexture(int width, int height) 
{
	Uint32 *dst;
	int row, col;
	void *pixels;
	int pitch;
	unsigned char rouge, vert, bleu;
 
    if (SDL_LockTexture(backGroundTexture, 0, &pixels, &pitch) != 0) 
	{
            std::cout << SDL_GetError() << std::endl;
            throw  "Error SDL_LockTexture";
    }

	for (row = 0; row < height; ++row) 
	{
		dst = (Uint32*)((Uint8*)pixels + row * pitch);

		rouge = Interpolation(104, 0, (float)row / (float)height);
		vert =  Interpolation(105, 0, (float)row / (float)height);
		bleu =  Interpolation(183, 40, (float)row / (float)height);
			
		for (col = 0; col < width; ++col) 
		{
			*dst++ = (0x00000000|(rouge<<24)|(vert<<16)|(bleu<<8));
		}
	}
 
    SDL_UnlockTexture(backGroundTexture);
}


void ScreenMenu::SetVisible(bool visible)
{
	for(std::vector<SDLTexte*>::iterator iter = listeTexte.begin(); iter != listeTexte.end(); iter++)
	{
		(*iter)->SetVisible(visible);
	}

	curseur->SetVisible(visible);

	this->visible = visible;
}


void ScreenMenu::Update()
{
	if(isActivated == true  &&  visible == true)
	{
		// Down
		if( SDLInput::GetInstance()->IsKeyPressed(SDL_SCANCODE_DOWN) == true)
		{
			// pour la selection
			if(menucanselected == true)
			{
				for(int i = selectTexteEnCour + 1; i < listeTexte.size(); i++)
				{
					if(listeTexte[i]->GetCanSelectTexte() == true)
					{
						SDLAudio::GetInstance()->PlaySound(SDLResources::GetInstance()->GetSound("Assets/Audio/Sound/Menu/Move.ogg"), SDLAudio::STEREO);
						curseur->SetPosition(listeTexte[i]->GetX() - 35, listeTexte[i]->GetY());
						selectTexteEnCour = i;

						break;
					}
				}
			}
		}
		// Up
		else if( SDLInput::GetInstance()->IsKeyPressed(SDL_SCANCODE_UP) == true)
		{
			// pour la selection
			if(menucanselected == true)
			{
				for(int i = selectTexteEnCour - 1; i >= 0; i--)
				{
					if(listeTexte[i]->GetCanSelectTexte() == true)
					{
						SDLAudio::GetInstance()->PlaySound(SDLResources::GetInstance()->GetSound("Assets/Audio/Sound/Menu/Move.ogg"), SDLAudio::STEREO);
						curseur->SetPosition(listeTexte[i]->GetX() - 35, listeTexte[i]->GetY());
						selectTexteEnCour = i;

						break;
					}
				}
			}
		}
		// Right
		else if( SDLInput::GetInstance()->IsKeyPressed(SDL_SCANCODE_RIGHT) == true)
		{
			// pour la selection
			if(menucanselected == true)
			{
				for(int i = selectTexteEnCour + numberMatrixCaseY; i < listeTexte.size(); i--)
				{
					if(listeTexte[i]->GetCanSelectTexte() == true)
					{
						SDLAudio::GetInstance()->PlaySound(SDLResources::GetInstance()->GetSound("Assets/Audio/Sound/Menu/Move.ogg"), SDLAudio::STEREO);
						curseur->SetPosition(listeTexte[i]->GetX() - 35, listeTexte[i]->GetY());
						selectTexteEnCour = i;

						break;
					}
				}
			}
		}
		// Left
		else if( SDLInput::GetInstance()->IsKeyPressed(SDL_SCANCODE_LEFT) == true)
		{
			// pour la selection
			if(menucanselected == true)
			{
				for(int i = selectTexteEnCour - numberMatrixCaseY; i >= 0; i--)
				{
					if(listeTexte[i]->GetCanSelectTexte() == true)
					{
						SDLAudio::GetInstance()->PlaySound(SDLResources::GetInstance()->GetSound("Assets/Audio/Sound/Menu/Move.ogg"), SDLAudio::STEREO);
						curseur->SetPosition(listeTexte[i]->GetX() - 35, listeTexte[i]->GetY());
						selectTexteEnCour = i;

						break;
					}
				}
			}
		}
		// Enter
		else if( SDLInput::GetInstance()->IsKeyPressed(SDL_SCANCODE_RETURN) == true)
		{
			// pour la selection
			if(menucanselected == true)
			{
				if(returnSelection == -1)
				{
					SDLAudio::GetInstance()->PlaySound(SDLResources::GetInstance()->GetSound("Assets/Audio/Sound/Menu/Select.ogg"), SDLAudio::STEREO);
					returnSelection = selectTexteEnCour;
				}
			}
		}
		// BACKSPACE
		else if( SDLInput::GetInstance()->IsKeyPressed(SDL_SCANCODE_BACKSPACE) == true)
		{
			// pour la selection
			if(menucanselected == true)
			{
				if(returnSelection == -1)
				{
					SDLAudio::GetInstance()->PlaySound(SDLResources::GetInstance()->GetSound("Assets/Audio/Sound/Menu/Back.ogg"), SDLAudio::STEREO);
					returnSelection = -2;
				}
			}
		}
	}
}